/***********************************************************************************
 * 文件名： soft_pwm.h
 * 版本： 2
 * 说明：
 * 		一个软件模拟的8位PWM控制器。
 *      在定时器中断中调用 SPwm_EvTimer ，PWM频率 = 中断频率/255。在程序启动时调用 SPwm_Init
 *  进行初始化。通过调用 SPwm_SetValue 设置PWM值（决定占空比），为0是始终输出OFF，为255时始
 *  终输出ON。ON 和 OFF 具体代表什么在配置文件中设置。还提供了开始和停止运行的API，以及刹车
 *  等API，具体见头文件。
 * 修改记录：
 * 	2021/04/21: 初版。 刘言。
 *  2022/04/01: 新增SPwm_GetState()接口，优化通道定义，支持多条语句
***********************************************************************************/
#ifndef _SOFT_PWM_H_
#define _SOFT_PWM_H_

#include <stddef.h>
#ifdef __NO_INCLUDE_PATH    // 如果有，定义在 stddef.h
#include "..\..\..\projects\prj\bsp\spwm_config.h"
#else
#include "spwm_config.h"
#endif

#include "..\..\polsys.h"



#define _SPwm_UpdataCH0()    \
{\
    if(_SPwm_Count < _SPwm_Value[0]){_SPwm_Ch0On();}\
    else {_SPwm_Ch0Off();}\
}

#if (SPWM_MAX_CH >=2)
#define _SPwm_UpdataCH1()    \
{\
    if(_SPwm_Count < _SPwm_Value[1]){_SPwm_Ch1On();}\
    else {_SPwm_Ch1Off();}\
}
#else
#define _SPwm_UpdataCH1()
#endif

#if (SPWM_MAX_CH >=3)
#define _SPwm_UpdataCH2()    \
{\
    if(_SPwm_Count < _SPwm_Value[2]){_SPwm_Ch2On();}\
    else {_SPwm_Ch2Off();}\
}
#else
#define _SPwm_UpdataCH2()
#endif

#if (SPWM_MAX_CH >=4)
#define _SPwm_UpdataCH3()    \
{\
    if(_SPwm_Count < _SPwm_Value[3]){_SPwm_Ch3On();}\
    else {_SPwm_Ch3Off();}\
}
#else
#define _SPwm_UpdataCH3()
#endif

#if (SPWM_MAX_CH >=5)
#define _SPwm_UpdataCH4()    \
{\
    if(_SPwm_Count < _SPwm_Value[4]){_SPwm_Ch4On();}\
    else {_SPwm_Ch4Off();}\
}
#else
#define _SPwm_UpdataCH4()
#endif

#if (SPWM_MAX_CH >=6)
#define _SPwm_UpdataCH5()    \
{\
    if(_SPwm_Count < _SPwm_Value[5]){_SPwm_Ch5On();}\
    else {_SPwm_Ch5Off();}\
}
#else
#define _SPwm_UpdataCH5()
#endif

#ifdef _SPWM_USE_MATCH_EVENT
#define _SPwm_Match()   \
{\
    if(_SPwm_Count == _SPWM_MATCH_VALUE)\
    {\
        _SPwm_Ev_Match();\
    }\
}
#else
#define _SPwm_Match()
#endif


// 为了伪函数代码优化暴露以下属性

extern bit _SPwm_Run;
extern u8 _SPwm_Count;
extern u8 _SPwm_Value[SPWM_MAX_CH];


// API

// 定时器中断中调用
// PWM周期 = 中断周期 * _SPWM_FULL_VALUE
// 需要自行初始化定时器中断，并在中断服务函数中调用本函数
#define SPwm_EvTimer()  \
{\
    if(_SPwm_Run)\
    {\
        _SPwm_UpdataCH0();\
        _SPwm_UpdataCH1();\
        _SPwm_UpdataCH2();\
        _SPwm_UpdataCH3();\
        _SPwm_UpdataCH4();\
        _SPwm_UpdataCH5();\
        _SPwm_Match();\
        _SPwm_Count++;\
        if(_SPwm_Count == _SPWM_FULL_VALUE)\
        {\
            _SPwm_Count=0;\
        }\
    }\
}

// 初始化 SPWM
// 将会调用配置的定时器初始化函数，初始化后立即运行
#define SPwm_Init() \
{\
    _SPwm_Run = true;\
    _SPwm_TimInit();\
}

// 获取运行状态
#define SPwm_GetState() _SPwm_Run

// 开始运行
// 计数变量会被清零
#define SPwm_Enable()   \
{\
    _SPwm_Count = 0;\
    _SPwm_Run = true;\
}

// 停止运行，在不需要使用时可以降低CPU占用率。
// 注意输出状态将会保持当前状态，建议先 SPwm_Brake 后再调用。
#define SPwm_Disable()  _SPwm_Run = false;

// 设置通道的PWM值
#define SPwm_SetValue(u8_ch, u8_value)  \
{\
    _SPwm_Value[u8_ch] = (u8_value);\
}

// 获取通道的PWM值
#define SPwm_GetValue(u8_ch)    _SPwm_Value[u8_ch]

// 清零计数变量
// 某些时候启动PWM输出时，需要第一个周期是完整的并能确保触发事件。
#define SPwm_ClrCount()         _SPwm_Count = 0

// 紧急刹车，对应的通道端口会立即OFF状态且PWM值被清零，不影响其它通道。
void SPwm_Brake(u8 ch);


#endif



